#pragma once
#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<queue>
const int default_capacity=5;
template<typename T>
class BlockQueue{
public:
     BlockQueue(int cap=default_capacity):_cap(cap),csleep_num(0),psleep_num(0){
        pthread_mutex_init(&_mutex,NULL);
        pthread_cond_init(&_full_cond,NULL);
        pthread_cond_init(&_empty_cond,NULL);
     }
     void Equeue(const T&val){
        //生产者调用
        pthread_mutex_lock(&_mutex);
        while(IsFull()){
            //阻塞等待
            //当被唤醒时必须还要竞争_mutex这把锁才能向下运行
            psleep_num++;
            //伪唤醒：条件不满足也被唤醒了
            pthread_cond_wait(&_full_cond,&_mutex);
            psleep_num--;
        }
        //使用while再检查一次100%确定不是伪唤醒
            //入队
            q.push(val);
            //通知消费者
            if(csleep_num>0){
                pthread_cond_signal(&_empty_cond);
            }
            pthread_mutex_unlock(&_mutex);
     }
     T Pop(){
        //消费者调用
        pthread_mutex_lock(&_mutex);
        while(IsEmpty()){
            //阻塞等待
            csleep_num++;
            pthread_cond_wait(&_empty_cond,&_mutex);
            csleep_num--;
        }
            //出队
            T val=q.front();
            q.pop();
            //通知生产者
            if(psleep_num>0){
                pthread_cond_signal(&_full_cond);
            }
            pthread_mutex_unlock(&_mutex);
            return val;
     }
     ~BlockQueue(){
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_full_cond);
        pthread_cond_destroy(&_empty_cond);
     }
private:
     bool IsFull(){
        return q.size()==_cap;
     }
     bool IsEmpty(){
        return q.empty();
     }
    std::queue<T> q;
    int _cap;//容量大小
    pthread_mutex_t _mutex;
    pthread_cond_t _full_cond;//生产者唤醒条件变量
    pthread_cond_t _empty_cond;//消费者唤醒条件变量
    int csleep_num;//消费者的个数
    int psleep_num;//生产者的个数
};